﻿using System;
using System.Collections.Generic;
using System.Data;
using Lightray.Hattrick.ChppLib.EntityTypes;
using Lightray.Hattrick.ChppLib;
using System.Linq;

namespace Lightray.Hattrick
{
    public abstract class BaseTeamModel : IModel
    {
        private bool _sortAsec;

        protected IDictionary<BasicPlayer, IEnumerable<ProgressRecord>> _progressReport;

        #region DataTable columns
        protected const string COL_NAME = "NAME";

        protected const string COL_SCORING = "SCR";
        protected const string COL_PLAYMAKING = "PM";
        protected const string COL_WINGER = "WNG";
        protected const string COL_PASSING = "PAS";
        protected const string COL_DEFENDING = "DEF";
        protected const string COL_KEEPING = "GK";
        protected const string COL_SETPIECES = "SP";

        protected const string COL_INJURY = "INJ";
        protected const string COL_AGE = "AGE";
        protected const string COL_CARDS = "CARDS";
        protected const string COL_SPECIALITY = "SPECIALITY";
        protected const string COL_PLAYER_INSTANCE = "PLAYER";

        #endregion

        public DataView Data { get; protected set; }

        public abstract bool HasProgressReport { get; }

        public event EventHandler DataChanged;
        protected void OnDataChanged(object sender, EventArgs e)
        {
            if (DataChanged != null)
                DataChanged(sender, e);
        }

        public virtual ModelColumnDescription GetColumnDescription(string columnName)
        {
            switch (columnName)
            {
                case COL_NAME:
                    return ModelColumnDescription.Name;

                case COL_SCORING:
                case COL_PLAYMAKING:
                case COL_WINGER:
                case COL_PASSING:
                case COL_DEFENDING:
                case COL_KEEPING:
                case COL_SETPIECES:
                    return ModelColumnDescription.Skill;

                case COL_SPECIALITY:
                    return ModelColumnDescription.Speciality;

                case COL_AGE:
                    return ModelColumnDescription.Age;

                case COL_INJURY:
                    return ModelColumnDescription.Injury;

                case COL_CARDS:
                    return ModelColumnDescription.Cards;

                case COL_PLAYER_INSTANCE:
                    return ModelColumnDescription.PlayerInstance;
            }

            return ModelColumnDescription.UnboundData;
        }

        public abstract PlayerRole GetRoleColumnName(string columnName);

        public virtual BasicPlayer PlayerFromRow(DataRowView dataRowView)
        {
            return dataRowView.Row[COL_PLAYER_INSTANCE] as BasicPlayer;
        }

        public KeyValuePair<string, ProgressCharacteristic>[] PlayerProgressFromRow(DataRowView dataRowView)
        {
            BasicPlayer player = PlayerFromRow(dataRowView);
            if (!playerIncludedInProgressReport(player))
                return null;

            var columnToProgressPairs =
                    from progressRecord in _progressReport[player]
                    where progressRecord.Type == ProgressType.PlayerAttributeChanged
                    select new KeyValuePair<string, ProgressCharacteristic>(columnNameFromProgressRecord(progressRecord),
                                                                            progressRecord.Characteristic);
            return columnToProgressPairs.ToArray();
        }          

        public void Sort(string columnName)
        {            
            Data.Sort = sortExpression(columnName);
            OnDataChanged(this, new EventArgs());
        }

        public abstract String[] UnlockedSkillsFromRow(DataRowView dataRowView);

        protected virtual string columnNameFromProgressRecord(ProgressRecord progressRecord)
        {
            switch (progressRecord.AffectedAttribute)
            {
                case ProgressAttributes.Age:
                    return COL_AGE;
                case ProgressAttributes.Cards:
                    return COL_CARDS;
                case ProgressAttributes.InjuryLevel:
                    return COL_INJURY;
                case ProgressAttributes.Skill:

                    switch (progressRecord.AffectedSkill)
                    {
                        case Skill.Keeper:
                            return COL_KEEPING;
                        case Skill.Playmaking:
                            return COL_PLAYMAKING;
                        case Skill.Scoring:
                            return COL_SCORING;
                        case Skill.Passing:
                            return COL_PASSING;
                        case Skill.Winger:
                            return COL_WINGER;
                        case Skill.Defending:
                            return COL_DEFENDING;
                        case Skill.SetPieces:
                            return COL_SETPIECES;
                    }
                    break;
            }

            return string.Empty;
        }

        private string sortExpression(string columnName)
        {
            
            // if a new column is sorted, than the default is descending order
            if (!Data.Sort.Contains(columnName))
                _sortAsec = false;
            else // otherwise flip the sort direction
                _sortAsec = !_sortAsec;

            return string.Format("{0} {1}",
                                 columnName,
                                 _sortAsec ? "ASC" : "DESC");
        }

        private bool playerIncludedInProgressReport(BasicPlayer player)
        {
            return _progressReport.ContainsKey(player);
        }                     
    }
}
